import { App } from "../../application";
import Const from "../../application/constants/Const";
import Events from "../../application/constants/Events";
import { Polyline, Polygon, Point } from "../../Docs";
import { InteractionEvent } from "../../processor/Mouse";


export default class EditRectangle {
    private app: App;
    private polyline: Polyline;
    private polygon: Polygon;
    private param: {alphaValue?: number, color?: string};
    private isOpen: boolean = false;
    private finishClickListener: Function;

    /**
     * 矩形编辑
     */
    constructor() {
        this.app = App.getInstance();
    }

    /**
     * 开启矩形的编辑
     * @param param 矩形编辑需要用到的参数
     * @param param.alphaValue 矩形的透明度
     * @param param.color 矩形的颜色
     * @param finishClickListener 结束时的监听事件, 该监听有一个参数: polygon, 即编辑完成的矩形
     */
    public openEdit(param:{alphaValue?: number, color?: string}, finishClickListener: Function){
        if (this.isOpen) {
            return;
        }

        this.param = param;
        this.finishClickListener = finishClickListener;

        this.register();
        this.isOpen = true;
    }

    /**
     * 关闭矩形的编辑
     */
    public closeEdit(){
        this.app.remove(this.polyline);
        this.app.remove(this.polygon);

        this.cancleEvent();
        this.isOpen = false;
    }
    
    private register() {
        this.app.on(Events.Click, this.handleLeftClickEvent, this);
        this.app.on(Events.MouseMove, this.handleMoveEvent, this);
        this.app.on(Events.RightClick, this.handleRightClickEvent, this);
        
        this.app.mouse.addRaycasterType(Events.MouseMove);  //开启鼠标移动时的射线拾取功能
    }

    private cancleEvent() {
        this.app.off(Events.Click, this.handleLeftClickEvent, this);
        this.app.off(Events.MouseMove, this.handleMoveEvent, this);
        this.app.off(Events.RightClick, this.handleRightClickEvent, this);

        this.app.mouse.removeRaycasterType(Events.MouseMove);  //关闭鼠标移动时的射线拾取功能
    }

    private handleLeftClickEvent(data: InteractionEvent) {
        let clickPoint: Point = data.lnglat;
        clickPoint.toEPSGWeb();

        if (!this.polyline) {
            this.polyline = new Polyline({color: this.param.color, lineWidth: 2});
            this.polyline.renderOrder = Infinity;
            this.app.add(this.polyline);

            this.polyline.addPoint(clickPoint);
            this.polyline.addPoint(clickPoint.clone());
            this.polyline.addPoint(clickPoint.clone());
            this.polyline.addPoint(clickPoint.clone());
            this.polyline.addPoint(clickPoint.clone());
        }else{
            this.cancleEvent();
            if(this.finishClickListener){
                let polygon = this.buildPolygon();
                this.finishClickListener(polygon);
            }
        }
    }

    private handleMoveEvent(data: InteractionEvent) {
        if (!this.polyline) {
            return;
        }
        let clickPoint: Point = data.lnglat.clone();
        clickPoint.toEPSGWeb();

        let firstPoint = this.polyline.getPointByIndex(0);

        let newSecondPoint = new Point(firstPoint.x, clickPoint.y, firstPoint.z, Const.EPSGType.EPSGWeb);
        this.polyline.updatePoint(1, newSecondPoint);

        let newThirdPoint = clickPoint;
        this.polyline.updatePoint(2, newThirdPoint);

        let newFourthPoint = new Point(clickPoint.x, firstPoint.y, clickPoint.z, Const.EPSGType.EPSGWeb);
        this.polyline.updatePoint(3, newFourthPoint);
    }
    
    private handleRightClickEvent(data: InteractionEvent) {
        if (!this.polyline) {
            return;
        }
        let clickPoint: Point = data.lnglat.clone();
        clickPoint.toEPSGWeb();

        this.cancleEvent();

        if(this.finishClickListener){
            let polygon = this.buildPolygon();
            this.finishClickListener(polygon);
        }
    }

    private buildPolygon() {
        this.app.remove(this.polyline);

        let pointArray = this.polyline.getPointArray();

        let polygonParam = Object.assign({pointArray: null,  transparent: false}, this.param);
        polygonParam.pointArray = pointArray;
        polygonParam.transparent = true;
        this.polygon = new Polygon(polygonParam);
        this.polygon.renderOrder = Infinity;
        this.app.add(this.polygon)
        return this.polygon;
    }
}